#include "ClientConnectionHandler.h"
#include "ClientConnectionsManager.h"

namespace AlgoTrading
{
	namespace ConnectionLibrary
	{

		ClientConnectionHandler::ClientConnectionHandler(boost::asio::io_service& io, std::auto_ptr<boost::asio::ip::tcp::socket>& s, ClientConnectionAcceptorPtr acceptor, ClientConnectionsManager& cm)
			: socket(s)
			, io_service(io)
			, connectionAcceptor(acceptor)
			, connectionsManager(cm)
		{
			socketReaderWriter = boost::shared_ptr<SocketReaderWriter>(new SocketReaderWriter(io_service, *socket, static_cast<SocketNotificationHandler&>(*this)));
		}

		ClientConnectionHandler::~ClientConnectionHandler(void)
		{
		}

		void ClientConnectionHandler::SetRequestProcessor(ClientRequestProcessorPtr requestProcessor)
		{
			this->clientRequestProcessor = requestProcessor;
		}

		void ClientConnectionHandler::SendNotification(const AlgoTrading::Messages::NotificationMessage& message)
		{
			OutputMessageBufferHolderPtr outputMessageBufferHolder(new OutputMessageBufferHolder());
			//TODO: refactor this
			message.Serialize(outputMessageBufferHolder->GetOutputStream());
			outputMessageBufferHolder->ParseMessageLength();
			
			socketReaderWriter->SendBuffer(outputMessageBufferHolder);
		}

		void ClientConnectionHandler::SendRequestResponse(const AlgoTrading::Messages::RequestResponse& message)
		{
			OutputMessageBufferHolderPtr outputMessageBufferHolder(new OutputMessageBufferHolder());
			//TODO: refactor this
			message.Serialize(outputMessageBufferHolder->GetOutputStream());
			outputMessageBufferHolder->ParseMessageLength();
			
			socketReaderWriter->SendBuffer(outputMessageBufferHolder);
		}

		void ClientConnectionHandler::ParseMessageData(std::istream& stream)
		{
			std::auto_ptr<AlgoTrading::Messages::ClientMessage> clientMessage = AlgoTrading::Messages::ClientMessage::Deserialize(stream);
			AlgoTrading::Messages::ClientMessage::ClientMessageType clientMessageType = clientMessage->GetClientMessageType();
			if (clientMessageType == AlgoTrading::Messages::ClientMessage::REQUEST_WITH_RESPONSE)
			{
				clientRequestProcessor->OnRequest(*static_cast<AlgoTrading::Messages::RequestWithResponse*>(clientMessage.get()));
			}
			else if (clientMessageType == AlgoTrading::Messages::ClientMessage::REQUEST_WITHOUT_RESPONSE)
			{
				clientRequestProcessor->OnRequest(*static_cast<AlgoTrading::Messages::RequestWithoutResponse*>(clientMessage.get()));
			}
		}

		void ClientConnectionHandler::Start()
		{
			socketReaderWriter->StartReading();
		}

		void ClientConnectionHandler::Stop()
		{
			socketReaderWriter->Disconnect();
		}

		void ClientConnectionHandler::OnError(const boost::system::error_code& error)
		{
			connectionAcceptor->OnError(error);
		}

		void ClientConnectionHandler::OnDisconnect()
		{
			connectionAcceptor->OnDisconnect();
			connectionsManager.Remove(shared_from_this());
		}

	}
}
